package la.iok.hzsvn.lewin.movie.cloud.service;

import com.github.pagehelper.Page;
import la.iok.hzsvn.lewin.movie.cloud.entity.OrgUnit;
import la.iok.hzsvn.lewin.movie.cloud.entity.Role;
import la.iok.hzsvn.lewin.movie.cloud.entity.User;
import la.iok.hzsvn.lewin.movie.cloud.entity.UserRole;
import la.iok.hzsvn.lewin.movie.cloud.mapper.UserRoleMapper;
import la.iok.hzsvn.lewin.movie.core.RoleEnum;
import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.exception.ErrorCode;
import la.iok.hzsvn.lewin.movie.core.model.UserRoleDetail;
import la.iok.hzsvn.lewin.movie.core.model.UserRoleVo;
import la.iok.hzsvn.lewin.movie.core.model.UserVo;
import la.iok.hzsvn.lewin.mybatis.model.PageVo;
import la.iok.hzsvn.lewin.mybatis.service.BaseServiceImpl;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.NotNullElement;
import la.iok.hzsvn.share.annotations.NullElement;
import la.iok.hzsvn.share.annotations.Nullable;
import la.iok.hzsvn.share.collection.IdOperators;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserRoleServiceImpl extends BaseServiceImpl<UserRole,UserRoleMapper,Long> implements UserRoleService{
    private final RoleService roleService;
    private final OrgUnitService orgUnitService;

    private final UserService userServer;

    @Lazy
    public UserRoleServiceImpl(UserRoleMapper userRoleMapper,
                               RoleService roleService,
                               OrgUnitService orgUnitService,
                               UserService userServer) {
        super(userRoleMapper);
        this.roleService = roleService;
        this.orgUnitService = orgUnitService;
        this.userServer = userServer;
    }

    @Override
    public Long save(@NotNull UserRole entity) {
        mapper.insertSelective(entity);
        return entity.getId();
    }

    @Nullable
    @Override
    public UserRole select(@Nullable Long userId,@Nullable Long roleId,@Nullable Long orgUnitId) {
        if(userId == null || roleId == null || orgUnitId == null){
            return null;
        }
        return mapper.select(userId,roleId,orgUnitId);
    }

    @Override
    public List<UserRoleVo> po2vo(@Nullable Collection<UserRole> userRoles) {
        if(CollectionUtils.isEmpty(userRoles)){
            return Collections.emptyList();
        }
        List<Role> roles = roleService.list(userRoles.stream().filter(Objects::nonNull).map(UserRole::getRoleId)
                .collect(Collectors.toSet()));
        return userRoles.stream().filter(Objects::nonNull).map(po->{
            UserRoleVo vo = new UserRoleVo();
            BeanUtils.copyProperties(po,vo);
            Role r = IdOperators.find(roles,po.getRoleId());
            vo.setRole(r != null? r.getName() : null);
            return vo;
        }).collect(Collectors.toList());
    }

    @NotNull
    @NotNullElement
    @Override
    public List<UserRole> userRoles(@Nullable Long userId) {
        if(userId == null){
            return Collections.emptyList();
        }
        return listByProperty("userId",userId);
    }

    @Override
    public boolean hasAnyAuthority(@Nullable Long userId, @NotNull Long orgUnitId, RoleEnum... roles) {
        Set<String> rs = roles(userId, orgUnitId);
        return Arrays.stream(roles).anyMatch(r->rs.contains(r.name()));
    }

    @NotNull
    private Set<String> roles(@Nullable Long userId, @NotNull Long orgUnitId) {
        List<UserRole> list = userRoles(userId);
        Set<Long> roleIds = list.stream().filter(ur->Objects.equals(ur.getOrgUnitId(), orgUnitId)).map(UserRole::getRoleId).collect(Collectors.toSet());
        return roleService.list(roleIds).stream().map(Role::getName).collect(Collectors.toSet());
    }

    @Override
    public boolean hasOnlyAuthority(Long userId, Long orgUnitId, RoleEnum role) {
        Set<String> rs = roles(userId,orgUnitId);
        return rs.size() == 1 && rs.contains(role.name());
    }

    @NotNull
    @NotNullElement
    @Override
    public List<UserRole> userRoles(@Nullable @NullElement Collection<Long> userIds) {
        return listInProperty("userId",userIds);
    }

    @Override
    public List<UserRoleDetail> details(Collection<UserRole> userRoles) {
        if(CollectionUtils.isEmpty(userRoles)){
            return Collections.emptyList();
        }
        //角色不会太多,所以直接全部查
        List<Role> roles = roleService.selectAll();
        Set<Long> orgUnitIds = userRoles.stream().filter(Objects::nonNull).map(UserRole::getOrgUnitId).collect(Collectors.toSet());
        List<OrgUnit> orgUnits = orgUnitService.list(orgUnitIds);
        return userRoles.stream().filter(Objects::nonNull).map(ur->{
            UserRoleDetail item = new UserRoleDetail();
            BeanUtils.copyProperties(ur,item);
            Role r = IdOperators.find(roles,ur.getRoleId());
            if(r != null){
                item.setRole(r.getName());
            }
            OrgUnit orgUnit = IdOperators.find(orgUnits,ur.getOrgUnitId());
            if(orgUnit != null){
                item.setOrgUnitName(orgUnit.getName());
                item.setOrgUnitType(orgUnit.getType());
            }
            return item;
        }).collect(Collectors.toList());
    }


    /**
     * @param token
     * @param orgUnitId
     * @param roleId
     * @return
     */
    @Override
    public PageVo<UserVo> selectOrgUnitroles(Token token, Long orgUnitId, Long roleId) {
        token.validAnyAuthority(RoleEnum.CarpoolMaster);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(orgUnitId, "查找","店铺不能为空");
        List<UserRole> list =selectRoles(orgUnitId, roleId);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotEquals(0, list.size(),"查找","未能查找数据");
        if (list.size()!=0) {

            List<UserVo> data = new ArrayList<>();

            for (UserRole userRole : list
            ) {
                User user = userServer.selectUser(userRole.getUserId());
                ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(user, "查找","未能查到相关数据");
                if (user != null) {
                    data.add(userServer.po2vo(user));
                }

            }
            PageVo<UserVo> pageVo = new PageVo<>();
            pageVo.setPages(1);
            pageVo.setTotal(list.size());
            pageVo.setSize(list.size());
            pageVo.setRecords(data);
            return pageVo;
        }
        return null;
    }


    @Override
    public List<UserRoleDetail> details(Long userId) {
        return details(userRoles(userId));
    }

    @Override
    public int userCount(@Nullable @NotNullElement Collection<Long> orgUnitIds) {
        if(CollectionUtils.isEmpty(orgUnitIds)){
            return 0;
        }
        return mapper.count(orgUnitIds);
    }

    /**
     * @param orgUnitId
     * @param roleId
     * @return
     */
    @Override
    public List<UserRole> selectRoles(Long orgUnitId , Long roleId)
    {
        return mapper.selectRoles(orgUnitId, roleId);
    }

    @Override
    public int increaseScore(Long userId, Long orgUnitId, Long score) {
        int i=0;
        i=mapper.increaseScore(userId,orgUnitId,score);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotEquals(0, i,"修改","修改失败");
        return i;
    }

    @Override
    public int reduceScore(Long userId, Long orgUnitId, Long score) {
        int i=0;
        i=mapper.reduceScore(userId,orgUnitId,score);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotEquals(0, i,"修改","修改失败");
        return i;
    }

    @Override
    public List<UserRole> selectScore(Long userId, Long orgUnitId) {
        List<UserRole>list=mapper.selectScore(userId,orgUnitId);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotEquals(0, list.size(),"查找","未能查找数据");
        return list;
    }
}




